package com.shop.cereshop.app.dl.logic.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.shop.cereshop.app.redis.service.api.StringRedisService;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.util.*;

/**
 * @program: dlshop
 * 描述：
 * @author: 我好帅
 * @create: 2021-07-28 14:12
 **/
@Slf4j
public class GetBackendToken {
    final static String url = "https://open.95516.com/open/access/1.0/backendToken";

    public static String getBackendToken(String appid, String secret, StringRedisService redis) {
        if (redis.get("YunBackendToken") == null) {
            Map<String, String> sortedParams = new HashMap<>();
            sortedParams.put("appId", appid);
            sortedParams.put("secret", secret);
            // 16位随机字符串
//        sortedParams.put("nonceStr", getRandomString(16));
            sortedParams.put("nonceStr", createNonceStr());
            // 以秒为单位
            sortedParams.put("timestamp", System.currentTimeMillis() / 1000 + "");
            // 签名值，签名因子包括(appId,nonceStr, secret, timestamp)
            String signContent = getSignContent(sortedParams);
            // 删除secret
            sortedParams.remove("secret");
            // appId,nonceStr, secret, timestamp
            sortedParams.put("signature", sha256(signContent.getBytes()));
            String strJson = JSON.toJSONString(sortedParams);
            String result = postJson(url, "application/json", strJson);
            log.info("获取云闪付backendToken===》" + result);
            JSONObject resultJson = JSON.parseObject(result);
            if ("00".equals(resultJson.get("resp"))) {
                JSONObject paramsJson = JSON.parseObject(String.valueOf(resultJson.get("params")));
                String t = String.valueOf(paramsJson.get("backendToken"));
                Integer time = (Integer) paramsJson.get("expiresIn");
                time *= 1000;
                redis.set("YunBackendToken", t, time);
                return t;
            }
        } else {
            return String.valueOf(redis.get("YunBackendToken"));
        }
        return null;
    }


    public static String getRandomString(int length) {
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(3);
            long result = 0;
            switch (number) {
                case 0:
                    result = Math.round(Math.random() * 25 + 65);
                    sb.append(String.valueOf((char) result));
                    break;
                case 1:
                    result = Math.round(Math.random() * 25 + 97);
                    sb.append(String.valueOf((char) result));
                    break;
                case 2:
                    sb.append(String.valueOf(new Random().nextInt(10)));
                    break;
            }
        }
        return sb.toString();
    }

    public static String getSignContent(Map<String, String> sortedParams) {
        StringBuffer content = new StringBuffer();
        List<String> keys = new ArrayList<>(sortedParams.keySet());
        Collections.sort(keys);
        int index = 0;
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = sortedParams.get(key);
            content.append((index == 0 ? "" : "&") + key + "=" + value);
            index++;
        }
        return content.toString();
    }

    public static String createNonceStr() {
        String sl = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 16; i++) {
            sb.append(sl.charAt(new Random().nextInt(sl.length())));
        }
        return sb.toString();
    }

    public static String sha256(byte[] data) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            return bytesToHex(md.digest(data));
        } catch (Exception ex) {
            log.info("Never happen.", ex);
            return null;
        }
    }

    public static String bytesToHex(byte[] bytes) {
        String hexArray = "0123456789abcdef";
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            int bi = b & 0xff;
            sb.append(hexArray.charAt(bi >> 4));
            sb.append(hexArray.charAt(bi & 0xf));
        }
        return sb.toString();
    }

    public static String postJson(String generalUrl, String contentType, String params) {
        try {
            URL url = new URL(generalUrl);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            // 设置通用的请求属性
            connection.setRequestProperty("Content-Type", contentType);
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setUseCaches(false);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            // 得到请求的输出流对象
            DataOutputStream out = new DataOutputStream(connection.getOutputStream());
            out.write(params.getBytes("UTF-8"));
            out.flush();
            out.close();

            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> headers = connection.getHeaderFields();
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = null;
            in = new BufferedReader(
                    new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String result = "";
            String getLine;
            while ((getLine = in.readLine()) != null) {
                result += getLine;
            }
            in.close();
            return result;
        } catch (Exception e) {
            log.info("发送请求失败:异常信息：" + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }
}
